<?php

namespace app\admin\controller\jskmsg;

use app\api\model\BaseModel;
use app\api\model\UserModel;
use app\api\model\UserMoneyLogModel;
use app\api\model\UserRedbagLogModel;
use app\common\controller\Backend;
use think\Db;
use think\exception\DbException;
use think\exception\PDOException;
use think\exception\ValidateException;
use think\Log;
use think\response\Json;

/**
 * 用户提现管理
 *
 * @icon fa fa-circle-o
 */
class Userwithdraw extends Backend
{

    /**
     * Userwithdraw模型对象
     * @var \app\admin\model\jskmsg\Userwithdraw
     */
    protected $model = null;

    //在进行请求时必须需要使用证书：cert 与 key 分别属于两个.pem文件
    private $SSLCERT_PATH = "/www/wwwroot/recovery.7scode.com/jushoukeback/application/api/cert/apiclient_cert.pem"; //微信证书
    private $SSLKEY_PATH =  "/www/wwwroot/recovery.7scode.com/jushoukeback/application/api/cert/apiclient_key.pem"; //证书秘钥

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\jskmsg\Userwithdraw;
        $this->view->assign("typeList", $this->model->getTypeList());
        $this->view->assign("statusList", $this->model->getStatusList());
    }



    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */

    /**
     * 查看
     *
     * @return string|Json
     * @throws \think\Exception
     * @throws DbException
     */
    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if (false === $this->request->isAjax()) {
            return $this->view->fetch();
        }
        //如果发送的来源是 Selectpage，则转发到 Selectpage
        if ($this->request->request('keyField')) {
            return $this->selectpage();
        }
        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
        $list = $this->model
            ->with('user')
            ->where($where)
            ->order($sort, $order)
            ->paginate($limit);
        $result = ['total' => $list->total(), 'rows' => $list->items()];
        return json($result);
    }

    /**
     * 编辑
     *
     * @param $ids
     * @return string
     * @throws DbException
     * @throws \think\Exception
     */
    public function edit($ids = null)
    {
        $row = $this->model->get($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
            $this->error(__('You have no permission'));
        }
        if (false === $this->request->isPost()) {
            $this->view->assign('row', $row);
            return $this->view->fetch();
        }
        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        if($row['status']==1){
            $this->error('该笔提现申请已经审核通过了');
        }
        $params = $this->preExcludeFields($params);
        $result = false;
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
                $row->validateFailException()->validate($validate);
            }
            //提现审核通过
            if($params['status']==1){
                //BaseModel::log('提现到微信','审核通过');
                //提现到微信
                //获取用户的openid
                $params['withdraw_id'] = date('YmdHis').rand(100000,999999);//提现订单号
                $user = UserModel::find($params['user_id']);
                if($params['type']=='balance'){
                    //余额提现
                    //用户的余额是否大于实际到账金额  amount 提现金额  fee 手续费  actual_amount 实际到账金额
                    if($user->balance < $params['actual_amount']){
                        $this->error('用户余额不足，提现失败');
                    }else{
                        //扣除提现金额
                        $before = $user->balance;//变更前余额
                        $userbalance = $before - $params['actual_amount'];
                        $user->balance = $userbalance;//变更后余额
                        $user->save();
                        //写进会员余额变动表中
                        UserMoneyLogModel::create([
                            'user_id' => $user->id,
                            'money' => '-'.$params['actual_amount'],
                            'before' => $before,
                            'after' => $userbalance,
                            'memo' => '余额提现',
                            'createtime' => time()
                        ]);
                    }
                }else{
                    //红包提现
                    //用户的红包是否大于实际到账金额红包
                    if($user->redbag < $params['actual_amount']){
                        $this->error('用户红包不足，提现失败');
                    }else{
                        //扣除提现金额
                        $before = $user->redbag;//变更前红包
                        $userredbag = $before - $params['actual_amount'];
                        $user->redbag = $userredbag;//变更后红包
                        $user->save();
                        //写进会员红包变动表中
                        UserRedbagLogModel::create([
                            'type' => '提现',
                            'user_id' => $user->id,
                            'redbag' => '-'.$params['actual_amount'],
                            'before' => $before,
                            'after' => $userredbag,
                            'memo' => '红包提现',
                            'createtime' => time()
                        ]);
                    }
                }

//                $openid = $user->openid;
//                $trade_no = $params['withdraw_id'];
//                $money = $params['amount']*100;
//                $desc = '用户提现到微信零钱';
//                $re = $this->wxtransfer($openid,$trade_no,$money,$desc);
//                if($re){
//                    if($re->return_code == 'SUCCESS' || $re->return_code == 'success'){
//                        Log::write('提现到微信操作成功');
//                    }else{
//                        Log::write('提现到微信操作失败');
//                        $this->error($re->return_msg);
//                    }
//                }else{
//                    $this->error('操作失败');
//                }
            }
            $result = $row->allowField(true)->save($params);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if (false === $result) {
            $this->error(__('No rows were updated'));
        }
        $this->success();
    }

    /*
	* 微信提现转付款到零钱
	* @access public
	* @param  string  $openid 微信用户openid
	* @param  string  $trade_no 订单号
	* @param  int     $money 金额
	* $param  string  $desc 付款备注
	*/
    public function wxtransfer($openid,$trade_no,$money,$desc)
    {
        BaseModel::log('提现到微信','微信提现转付款到零钱方法');
        $data = [
            'mch_appid'         => config('wx.app_id'),
            'mchid'             => config('wx.mch_id'),
            'nonce_str'         => $this->createNoncestr(),//随机字符串 strtoupper(md5(uniqid(microtime(true),true))),
            'partner_trade_no'  => $trade_no,//订单号
            'openid'            => $openid,//用户openid
            'check_name'        => 'NO_CHECK',
            'amount'            => $money,//金额
            'desc'              => $desc,//描述信息
            'spbill_create_ip'  => request()->ip(),//服务器ip
        ];//请求参数拼凑
        $data['sign'] = $this->getSign($data);//sign进行签名
        $xmldata = $this->arrToXml($data);//数组转为xml格式
        BaseModel::log('提现到微信','xml数据格式：'.$xmldata);
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'; //微信付款到零钱提现的地址
        Log::write('微信curl请求');
        $xml =  $this->curl_post_ssl($xmldata,$url); //Curl请求
        BaseModel::log('提现到微信',$xml);
        $res = $this->xmlToArray($xml);
        return $res;

//        $content = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
//        BaseModel::log('提现到微信',$content);
//        return $content;
    }

    //随机字符串，不长于32位
    public function createNoncestr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /*
      生成签名
   */
    function getSign($data)
    {
        $key = config('wx.key');//商户秘钥 微信支付平台-》 API安全-》设置APIv2密钥
        // 关联排序
        ksort($data);
        // 字典排序
        $str = http_build_query($data);
        // 添加商户密钥
        $str .= '&key=' . $key;
        // 清理空格
        $str = urldecode($str);
        $str = md5($str);
        // 转换大写
        $result = strtoupper($str);
        return $result;
    }

    /**
     * 数组转XML
     * @param $data
     * @return string
     */
    function arrToXml($data)
    {
        $xml = "<xml>";
        //  遍历组合
        foreach ($data as $k => $v) {
            $xml .= '<' . $k . '>' . $v . '</' . $k . '>';
        }
        $xml .= '</xml>';
        return $xml;
    }

    /**
     * XML转数组
     * @param string
     * return $data
     * */
    function xmlToArray($xml)
    {
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        BaseModel::log('提现到微信',$values);
        return $values;
    }

    //将数组转成uri字符串
    function formatBizQueryParaMap($paraMap, $urlencode)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v)
        {
            if($urlencode)
            {
                $v = urlencode($v);
            }
            $buff .= strtolower($k) . "=" . $v . "&";
        }
        $reqPar = '';
        if (strlen($buff) > 0)
        {
            $reqPar = substr($buff, 0, strlen($buff)-1);
        }
        return $reqPar;
    }

    /**
     * [curl_post_ssl 发送curl_post数据]
     * @param  [type]  $url     [发送地址]
     * @param  [type]  $xmldata [发送文件格式]
     * @param  [type]  $second [设置执行最长秒数]
     * @param  [type]  $aHeader [设置头部]
     * @return [type]           [description]
     */
    function curl_post_ssl($xmldata,$url, $second = 30, $aHeader = array())
    {
        $isdir = ROOT_PATH . '/application/api/cert/';//证书位置;绝对路径
        $ch = curl_init();//初始化curl
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);//设置执行最长秒数
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_URL, $url);//抓取指定网页
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// 终止从服务端进行验证
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');//证书类型
        curl_setopt($ch, CURLOPT_SSLCERT, $isdir . 'apiclient_cert.pem');//证书位置
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');//CURLOPT_SSLKEY中规定的私钥的加密类型
        curl_setopt($ch, CURLOPT_SSLKEY, $isdir . 'apiclient_key.pem');//证书位置
        if (count($aHeader) >= 1) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);//设置头部
        }
        curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xmldata);//全部数据使用HTTP协议中的"POST"操作来发送
        $data = curl_exec($ch);//执行回话
        BaseModel::log('提现到微信', $data);
        if ($data) {
            curl_close($ch);
            return $this->xmlToArray($data);
        } else {
            $error = curl_errno($ch);
            echo "call faild, errorCode:$error\n";
            curl_close($ch);
            return false;
        }
    }

    //需要使用证书的请求
    private function postXmlSSLCurl($xml,$url,$second=30)
    {
        BaseModel::log('提现到微信',1);
        $ch = curl_init();
        $params[CURLOPT_URL] = $url; //请求url地址
        $params[CURLOPT_HEADER] = false; //是否返回响应头信息
        $params[CURLOPT_RETURNTRANSFER] = true; //是否将结果返回
        $params[CURLOPT_FOLLOWLOCATION] = true; //是否重定向
        $params[CURLOPT_POST] = true;
        $params[CURLOPT_POSTFIELDS] = $xml;
        $params[CURLOPT_SSL_VERIFYPEER] = false;
        $params[CURLOPT_SSL_VERIFYHOST] = false;
        //以下是证书相关代码
        $params[CURLOPT_SSLCERTTYPE] = 'PEM';
        $params[CURLOPT_SSLCERT] = ROOT_PATH."application/api/cert/apiclient_cert.pem";//绝对路径
        BaseModel::log('提现到微信',2);
        $params[CURLOPT_SSLKEYTYPE] = 'PEM';
        $params[CURLOPT_SSLKEY] = getcwd()."application/api/cert/apiclient_key.pem";//绝对路径
        BaseModel::log('提现到微信',3);
        curl_setopt_array($ch, $params); //传入curl参数
        $content = curl_exec($ch); //执行
        curl_close($ch); //
        BaseModel::log('提现到微信','curl请求：'.$content);
        return $content;
    }

    /*
    * 获取用户真实IP地址
    */
    public function get_ip()
    {
        if(!empty($_SERVER['HTTP_CLIENT_IP'])){
            $cip = $_SERVER['HTTP_CLIENT_IP'];
        }
        else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
            $cip = $_SERVER["HTTP_X_FORWARDED_FOR"];
        }
        else if(!empty($_SERVER["REMOTE_ADDR"])){
            $cip = $_SERVER["REMOTE_ADDR"];
        }else{
            $cip = '';
        }
        preg_match("/[\d\.]{7,15}/", $cip, $cips);
        $cip = isset($cips[0]) ? $cips[0] : 'unknown';
        unset($cips);
        return $cip;
    }

}
